package task2;

import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

public class FruitBasket {
	
	static class Fruit {
		protected int id;
		
		Fruit(int id) {
			this.id = id;
		}
		
		Fruit(Fruit f) {
			this.id = f.id;
		}
		
		public String toString() {
			return ("" + id);
		}
	}
	
	static class Apple extends Fruit implements Comparable<Apple> {		
				
		Apple(int id) {
			super(id);			
		}

		public int compareTo(Apple arg0) {
			if (id < arg0.id) {
				return -1;
			}
			
			if (id == arg0.id) {
				return 0;
			}
			
			return 1;
		}
		
	}
	
	static class RedApple extends Apple {

		RedApple(int id) {
			super(id);			
		}
		
	}
	
	static class Orange extends Fruit {

		Orange(int id) {
			super(id);			
		}
		
	}
	
	static class Melon {
		
	}
	
	public static <T extends Fruit, P extends Fruit>
		void copyAll(Collection<T> in, Collection<P> out) {
		if (in == null || out == null) {
			throw new NullPointerException();
		}
		
		if (in != out) { 
			for (T o : in) {
				P p = (P) new Fruit(o);
				out.add(p);
			}
		} else {
			LinkedList<T> buffer = new LinkedList<T>();
			for (T o : in) {
				buffer.add(o);
			}
			
			for (T o : buffer) {
				P p = (P) new Fruit(o);
				out.add(p);
			}
		}
	}
	
	public static <T extends Fruit & Comparable<T>> Collection<T>
		copyGreater(Collection<T> in, T threshold) throws InstantiationException, IllegalAccessException {
		Class<? extends Collection<T>> collectionClass = (Class<? extends Collection<T>>) in.getClass();
		Collection<T> res = (Collection<T>) collectionClass.newInstance();
		
		for (T o : in) {
			Integer comparationResult = 0;
			try {
				comparationResult = (Integer) o.getClass().getMethod("compareTo", o.getClass()).invoke(o, threshold);
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (comparationResult > 0) {
				res.add(o);
			}
		}
		
		return res;
	}

	public static void main(String[] args) {
		List<Fruit> fr = new LinkedList<Fruit>();
		List<Apple> app = new LinkedList<Apple>();
		List<Orange> or = new LinkedList<Orange>();
		List<RedApple> rapp = new LinkedList<RedApple>();
		List<Melon> mel = new LinkedList<Melon>();
		fr.add(new Fruit(1));
		or.add(new Orange(10));
		rapp.add(new RedApple(100));
		copyAll(or, fr);
		copyAll(rapp, fr);
		copyAll(rapp, app);
		copyAll(rapp, rapp);
		System.out.println(fr);
		System.out.println(or);
		System.out.println(app);
		System.out.println(rapp);
		
		app.clear();
		app.add(new Apple(100));
		app.add(new Apple(10));
		app.add(new Apple(1));
		System.out.println(app);
		Collection<Apple> app2 = new LinkedList<Apple>();
		try {
			app2 = copyGreater(app, new Apple(5));
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(app2);
	}
}
